package com.rickpan.controller;

import com.rickpan.common.ApiResponse;
import com.rickpan.entity.ProjectTask;
import com.rickpan.service.ProjectTaskService;
import com.rickpan.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 项目任务管理控制器
 * 
 * @author RickPan Team
 * @since 2024-01-15
 */
@RestController
@RequestMapping("/api/tasks")
@Tag(name = "项目任务管理", description = "项目任务管理相关接口")
public class ProjectTaskController {

    private static final Logger logger = LoggerFactory.getLogger(ProjectTaskController.class);

    @Autowired
    private ProjectTaskService taskService;

    /**
     * 创建任务
     */
    @PostMapping
    @Operation(summary = "创建任务", description = "在项目中创建新任务")
    public ApiResponse<ProjectTask> createTask(@Valid @RequestBody CreateTaskRequest request) {
        logger.info("创建任务请求: {}", request.getTitle());

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 创建任务实体
        ProjectTask task = new ProjectTask();
        task.setProjectId(request.getProjectId());
        task.setTitle(request.getTitle());
        task.setDescription(request.getDescription());
        task.setPriority(request.getPriority());
        task.setAssigneeId(request.getAssigneeId());
        task.setCreatorId(userId);
        task.setDueDate(request.getDueDate());
        task.setEstimatedHours(request.getEstimatedHours());
        
        ProjectTask createdTask = taskService.createTask(task);
        return ApiResponse.success("任务创建成功", createdTask);
    }

    /**
     * 更新任务
     */
    @PutMapping("/{taskId}")
    @Operation(summary = "更新任务", description = "更新任务信息")
    public ApiResponse<ProjectTask> updateTask(
            @Parameter(description = "任务ID") @PathVariable Long taskId,
            @Valid @RequestBody UpdateTaskRequest request) {
        logger.info("更新任务请求: {}", taskId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!taskService.hasTaskManagePermission(taskId, userId)) {
            return ApiResponse.error("无权限管理此任务");
        }
        
        // 更新任务实体
        ProjectTask task = taskService.findById(taskId)
                .orElseThrow(() -> new RuntimeException("任务不存在"));
        
        task.setTitle(request.getTitle());
        task.setDescription(request.getDescription());
        task.setPriority(request.getPriority());
        task.setAssigneeId(request.getAssigneeId());
        task.setDueDate(request.getDueDate());
        task.setEstimatedHours(request.getEstimatedHours());
        task.setActualHours(request.getActualHours());
        
        ProjectTask updatedTask = taskService.updateTask(task);
        return ApiResponse.success("任务更新成功", updatedTask);
    }

    /**
     * 删除任务
     */
    @DeleteMapping("/{taskId}")
    @Operation(summary = "删除任务", description = "删除指定任务")
    public ApiResponse<Void> deleteTask(
            @Parameter(description = "任务ID") @PathVariable Long taskId) {
        logger.info("删除任务请求: {}", taskId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!taskService.hasTaskManagePermission(taskId, userId)) {
            return ApiResponse.error("无权限管理此任务");
        }
        
        taskService.deleteTask(taskId);
        return ApiResponse.success("任务删除成功");
    }

    /**
     * 获取任务详情
     */
    @GetMapping("/{taskId}")
    @Operation(summary = "获取任务详情", description = "根据ID获取任务详细信息")
    public ApiResponse<ProjectTask> getTask(
            @Parameter(description = "任务ID") @PathVariable Long taskId) {
        logger.info("获取任务详情: {}", taskId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!taskService.hasTaskViewPermission(taskId, userId)) {
            return ApiResponse.error("无权限查看此任务");
        }
        
        ProjectTask task = taskService.findById(taskId)
                .orElseThrow(() -> new RuntimeException("任务不存在"));
        
        return ApiResponse.success("获取成功", task);
    }

    /**
     * 获取项目任务列表
     */
    @GetMapping("/project/{projectId}")
    @Operation(summary = "获取项目任务列表", description = "获取指定项目的所有任务")
    public ApiResponse<List<ProjectTask>> getProjectTasks(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "任务状态") @RequestParam(required = false) ProjectTask.Status status) {
        logger.info("获取项目任务列表: {}", projectId);

        List<ProjectTask> tasks;
        if (status != null) {
            tasks = taskService.findTasksByProjectAndStatus(projectId, status);
        } else {
            tasks = taskService.findTasksByProject(projectId);
        }
        
        return ApiResponse.success("获取成功", tasks);
    }

    /**
     * 分页获取项目任务列表
     */
    @GetMapping("/project/{projectId}/page")
    @Operation(summary = "分页获取项目任务列表", description = "分页获取指定项目的任务")
    public ApiResponse<Page<ProjectTask>> getProjectTasksPage(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "10") int size,
            @Parameter(description = "任务状态") @RequestParam(required = false) ProjectTask.Status status) {
        logger.info("分页获取项目任务列表: {}, page: {}, size: {}", projectId, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<ProjectTask> tasks;
        
        if (status != null) {
            tasks = taskService.findTasksByProjectAndStatus(projectId, status, pageable);
        } else {
            tasks = taskService.findTasksByProject(projectId, pageable);
        }
        
        return ApiResponse.success("获取成功", tasks);
    }

    /**
     * 获取用户任务列表
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取用户任务列表", description = "获取指定用户的所有任务")
    public ApiResponse<List<ProjectTask>> getUserTasks(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "任务状态") @RequestParam(required = false) ProjectTask.Status status) {
        logger.info("获取用户任务列表: {}", userId);

        List<ProjectTask> tasks;
        if (status != null) {
            tasks = taskService.findTasksByAssigneeAndStatus(userId, status);
        } else {
            tasks = taskService.findTasksByAssignee(userId);
        }
        
        return ApiResponse.success("获取成功", tasks);
    }

    /**
     * 搜索任务
     */
    @GetMapping("/project/{projectId}/search")
    @Operation(summary = "搜索任务", description = "在项目中搜索任务")
    public ApiResponse<List<ProjectTask>> searchTasks(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "搜索关键词") @RequestParam String keyword) {
        logger.info("搜索任务: {}, 关键词: {}", projectId, keyword);

        List<ProjectTask> tasks = taskService.searchTasks(projectId, keyword);
        return ApiResponse.success("搜索成功", tasks);
    }

    /**
     * 更新任务状态
     */
    @PutMapping("/{taskId}/status")
    @Operation(summary = "更新任务状态", description = "更新任务的状态")
    public ApiResponse<Void> updateTaskStatus(
            @Parameter(description = "任务ID") @PathVariable Long taskId,
            @Parameter(description = "新状态") @RequestParam ProjectTask.Status status) {
        logger.info("更新任务状态: {}, 状态: {}", taskId, status);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!taskService.hasTaskManagePermission(taskId, userId)) {
            return ApiResponse.error("无权限管理此任务");
        }
        
        taskService.updateTaskStatus(taskId, status);
        return ApiResponse.success("状态更新成功");
    }

    /**
     * 分配任务
     */
    @PutMapping("/{taskId}/assign")
    @Operation(summary = "分配任务", description = "为任务分配执行者")
    public ApiResponse<Void> assignTask(
            @Parameter(description = "任务ID") @PathVariable Long taskId,
            @Parameter(description = "分配者ID") @RequestParam Long assigneeId) {
        logger.info("分配任务: {}, 分配给: {}", taskId, assigneeId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!taskService.hasTaskManagePermission(taskId, userId)) {
            return ApiResponse.error("无权限管理此任务");
        }
        
        taskService.assignTask(taskId, assigneeId);
        return ApiResponse.success("任务分配成功");
    }

    /**
     * 获取任务统计信息
     */
    @GetMapping("/project/{projectId}/statistics")
    @Operation(summary = "获取任务统计信息", description = "获取项目的任务统计数据")
    public ApiResponse<ProjectTaskService.TaskStatistics> getTaskStatistics(
            @Parameter(description = "项目ID") @PathVariable Long projectId) {
        logger.info("获取任务统计信息: {}", projectId);

        ProjectTaskService.TaskStatistics statistics = taskService.getTaskStatistics(projectId);
        return ApiResponse.success("获取成功", statistics);
    }

    /**
     * 获取用户任务统计信息
     */
    @GetMapping("/user/{userId}/statistics")
    @Operation(summary = "获取用户任务统计信息", description = "获取用户的任务统计数据")
    public ApiResponse<ProjectTaskService.TaskStatistics> getUserTaskStatistics(
            @Parameter(description = "用户ID") @PathVariable Long userId) {
        logger.info("获取用户任务统计信息: {}", userId);

        ProjectTaskService.TaskStatistics statistics = taskService.getUserTaskStatistics(userId);
        return ApiResponse.success("获取成功", statistics);
    }

    /**
     * 创建任务请求DTO
     */
    public static class CreateTaskRequest {
        private Long projectId;
        private String title;
        private String description;
        private ProjectTask.Priority priority;
        private Long assigneeId;
        private LocalDateTime dueDate;
        private Integer estimatedHours;

        // Getter 和 Setter
        public Long getProjectId() { return projectId; }
        public void setProjectId(Long projectId) { this.projectId = projectId; }

        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }

        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }

        public ProjectTask.Priority getPriority() { return priority; }
        public void setPriority(ProjectTask.Priority priority) { this.priority = priority; }

        public Long getAssigneeId() { return assigneeId; }
        public void setAssigneeId(Long assigneeId) { this.assigneeId = assigneeId; }

        public LocalDateTime getDueDate() { return dueDate; }
        public void setDueDate(LocalDateTime dueDate) { this.dueDate = dueDate; }

        public Integer getEstimatedHours() { return estimatedHours; }
        public void setEstimatedHours(Integer estimatedHours) { this.estimatedHours = estimatedHours; }
    }

    /**
     * 更新任务请求DTO
     */
    public static class UpdateTaskRequest {
        private String title;
        private String description;
        private ProjectTask.Priority priority;
        private Long assigneeId;
        private LocalDateTime dueDate;
        private Integer estimatedHours;
        private Integer actualHours;

        // Getter 和 Setter
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }

        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }

        public ProjectTask.Priority getPriority() { return priority; }
        public void setPriority(ProjectTask.Priority priority) { this.priority = priority; }

        public Long getAssigneeId() { return assigneeId; }
        public void setAssigneeId(Long assigneeId) { this.assigneeId = assigneeId; }

        public LocalDateTime getDueDate() { return dueDate; }
        public void setDueDate(LocalDateTime dueDate) { this.dueDate = dueDate; }

        public Integer getEstimatedHours() { return estimatedHours; }
        public void setEstimatedHours(Integer estimatedHours) { this.estimatedHours = estimatedHours; }

        public Integer getActualHours() { return actualHours; }
        public void setActualHours(Integer actualHours) { this.actualHours = actualHours; }
    }
}
